import os
import random

import redis
from django.shortcuts import render, redirect
from rest_framework.views import APIView
from rest_framework.response import Response
from order.models import *
from shop.settings import BASE_DIR
from user.views import check_login
from django.db import transaction
from datetime import datetime

from alipay.aop.api.AlipayClientConfig import AlipayClientConfig
from alipay.aop.api.DefaultAlipayClient import DefaultAlipayClient, verify_with_rsa
from alipay.aop.api.domain.AlipayTradePagePayModel import AlipayTradePagePayModel
from alipay.aop.api.request.AlipayTradePagePayRequest import AlipayTradePagePayRequest
from shop.settings import ALIPAY_APPID, ALIPAY_SERVER_URL, ALIPAY_APP_PRIVATE_KEY, ALIPAY_PUBLIC_KEY


# Create your views here.
class OrderView(APIView):

    @check_login
    def get(self, request):
        """获取当前用户的所有订单"""
        user_id = request.user_id

        order_list = OrderModel.objects.filter(user_id=user_id).all()

        return Response({
            "code": 200,
            "msg": "ok",
            "data": [
                [
                    {
                        "orderID": i.o_id,  # i 是订单对象
                        "createdTime": i.create_time,
                        "productID": j.goods_id,  # j 是 订单下某一个订单商品对象
                        "productImg": j.goods.img,  # j.goods 根据goods_id 外键，找到商品对象
                        "productName": j.goods.sku_name,
                        "productPrice": j.price,
                        "productNum": j.count,
                        "payStatus": i.get_status_display(),
                    } for j in i.ordergoodsmodel_set.all()  # 订单下商品
                ] for i in order_list  # 我的订单
            ]
        })

    @check_login
    def post(self, request):
        # 接收参数
        goods_list = request.data["productsArr"]
        addr_id = request.data["addrID"]
        pay_method = request.data["payMethod"]
        user_id = request.user_id
        pay_method = int(pay_method)

        # 校验参数
        if len(goods_list) == 0:
            return Response({
                "code": 400,
                "msg": "未选择商品"
            })

        addr_info = AddressModel.objects.filter(id=addr_id).first()
        if not addr_info or addr_info.user_id != user_id:
            return Response({
                "code": 400,
                "msg": "收货地址不存在"
            })

        if pay_method not in [0, 1, 2]:
            return Response({
                "code": 400,
                "msg": "支付方式不允许"
            })

        # 增删改查
        rds = redis.Redis(host="127.0.0.1", db=2)
        with transaction.atomic():
            point = transaction.savepoint()
            try:

                # 生成绝不重复的订单号。32位。
                while True:
                    order_id = datetime.now().strftime("%Y%m%d%H%M%S") \
                               + str(user_id).zfill(8) \
                               + str(random.randint(10000, 99999)) \
                               + str(random.randint(10000, 99999))
                    o_info = OrderModel.objects.filter(o_id=order_id).first()
                    if not o_info:
                        break

                order_info = OrderModel.objects.create(
                    user_id=user_id,
                    status=0,
                    pay_type=pay_method,
                    addr_id=addr_id,
                    total_count=0,
                    total_amount=0,
                    o_id=order_id
                )

                for i in goods_list:
                    goods_info = GoodsModel.objects.filter(id=i["productID"]).first()
                    if not goods_info:
                        continue

                    # 判断库存是否充足
                    if goods_info.stock < i["num"]:
                        continue

                    # 减库存，加销量
                    goods_info.stock -= i["num"]
                    goods_info.count += i["num"]
                    goods_info.save()

                    OrderGoodsModel.objects.create(
                        goods_id=i["productID"],
                        count=i["num"],
                        price=goods_info.selling_price,
                        order_id=order_info.id
                    )
                    # 给主订单添加价格和数量
                    order_info.total_count += i["num"]
                    order_info.total_amount += i["num"] * goods_info.selling_price

                    # 删除购物车中的数据
                    rds.hdel("cart_%s" % user_id, i["productID"])
                    rds.srem("cart_select_%s" % user_id, i["productID"])

                order_info.save()
                transaction.savepoint_commit(point)

                # 给支付宝下单，下单完成以后，返回支付链接
                pay_url = self._create_order(order_info.o_id, float(order_info.total_amount), "购买商品")

                return Response({
                    "code": 200,
                    "msg": "下单成功",
                    "data": {
                        "url": pay_url
                    }
                })
            except Exception as e:
                print(e)
                transaction.savepoint_rollback(point)
                return Response({
                    "code": 200,
                    "msg": "下单失败"
                })

    @check_login
    def put(self, request):
        order_id = request.data.get("orderID")
        user_id = request.user_id

        order_info = OrderModel.objects.filter(o_id=order_id).first()
        if not order_info:
            return Response({
                "code": 400,
                "msg": "订单不存在"
            })

        if order_info.user_id != user_id:
            return Response({
                "code": 400,
                "msg": "无权支付"
            })

        if order_info.status != 0:
            return Response({
                "code": 400,
                "msg": "订单状态不允许"
            })

        url = self._create_order(order_info.o_id, float(order_info.total_amount), "购买商品")

        return Response({
            "code": 200,
            "msg": "下单成功",
            "data": {
                "url": url,
            }
        })

    @check_login
    def delete(self, request):
        order_id = request.query_params.get("order_id")
        goods_id = request.query_params.get("goods_id")
        user_id = request.user_id

        order_info = OrderModel.objects.filter(o_id=order_id).first()
        if not order_info:
            return Response({
                "code": 400,
                "msg": "订单不存在"
            })

        if order_info.user_id != user_id:
            return Response({
                "code": 400,
                "msg": "无权支付"
            })

        ordergoods_info = order_info.ordergoodsmodel_set.filter(goods_id=goods_id).first()
        if not ordergoods_info:
            return Response({
                "code": 400,
                "msg": "订单下无此商品"
            })

        with transaction.atomic():
            point = transaction.savepoint()
            try:

                if order_info.ordergoodsmodel_set.count() == 1:
                    ordergoods_info.delete()
                    order_info.delete()
                else:
                    order_info.total_amount -= (ordergoods_info.count * ordergoods_info.price)
                    order_info.total_count -= ordergoods_info.count
                    order_info.save()
                    ordergoods_info.delete()

                transaction.savepoint_commit(point)  # 提交事务

                return Response({
                    "code": 200,
                    "msg": "删除成功"
                })

            except Exception as e:
                transaction.savepoint_rollback(point)  # 回滚事务
                return Response({
                    "code": 400,
                    "msg": "删除失败"
                })

    def _create_order(self, id, total_amount, subjuct):
        """支付宝下单"""
        alipay_client_config = AlipayClientConfig()
        alipay_client_config.server_url = ALIPAY_SERVER_URL
        alipay_client_config.app_id = ALIPAY_APPID
        alipay_client_config.app_private_key = ALIPAY_APP_PRIVATE_KEY
        alipay_client_config.alipay_public_key = ALIPAY_PUBLIC_KEY

        # jnjhoh1548@sandbox.com

        client = DefaultAlipayClient(alipay_client_config=alipay_client_config)  # 实例化客户端对象

        # 对照接口文档，构造请求对象
        model = AlipayTradePagePayModel()
        model.out_trade_no = id  # 商户订单号
        model.total_amount = total_amount  # 支付金额
        model.subject = subjuct  # 订单标题
        # model.body = "支付宝测试"  # 订单内容
        model.product_code = "FAST_INSTANT_TRADE_PAY"  # 产品码，固定
        request = AlipayTradePagePayRequest(biz_model=model)  # 调用网站支付接口，下订单
        request.return_url = "http://127.0.0.1:8000/order/notify/"
        # 得到构造的请求，如果http_method是GET，则是一个带完成请求参数的url，如果http_method是POST，则是一段HTML表单片段
        response = client.page_execute(request, http_method="GET")
        return response


class NotifyView(APIView):
    def get(self, request):
        print(request.query_params)

        rs = self.check_pay(request.query_params.dict())
        if not rs:
            return Response({
                "code": 400,
                "msg": "非法请求"
            })
        # 根据订单号，找到订单。修改订单状态
        order_id = request.query_params.get("out_trade_no")

        order_info = OrderModel.objects.filter(o_id=order_id).first()
        if not order_info:
            return Response({
                "code": 400,
                "msg": "订单不存在"
            })

        if order_info.status != 0:
            return Response({
                "code": 400,
                "msg": "订单状态不允许"
            })

        order_info.status = 1
        order_info.save()

        return redirect("http://localhost:8080/#/order")

    def check_pay(self, params):  # 定义检查支付结果的函数
        sign = params.pop('sign', None)  # 取出签名
        params.pop('sign_type')  # 取出签名类型
        params = sorted(params.items(), key=lambda e: e[0], reverse=False)  # 取出字典元素按key的字母升序排序形成列表
        message = "&".join(u"{}={}".format(k, v) for k, v in params).encode()  # 将列表转为二进制参数字符串
        try:
            alipay_public_key = ALIPAY_PUBLIC_KEY.replace("-----BEGIN RSA PUBLIC KEY-----\n", "")
            alipay_public_key = alipay_public_key.replace("\n-----END RSA PUBLIC KEY-----", "")

            status = verify_with_rsa(alipay_public_key.encode('utf-8').decode('utf-8'), message,
                                     sign)  # 验证签名并获取结果
            return status  # 返回验证结果
        except Exception as e:  # 如果验证失败，返回假值。
            print(e)
            return False


class ConfirmView(APIView):
    @check_login
    def put(self, request):
        """确认收货"""
        user_id = request.user_id
        order_id = request.data.get("orderID")

        order_info = OrderModel.objects.filter(o_id=order_id).first()
        if not order_info:
            return Response({
                "code": 400,
                "msg": "订单不存在"
            })

        if order_info.user_id != user_id:
            return Response({
                "code": 400,
                "msg": "无权支付"
            })

        if order_info.status != 2:
            return Response({
                "code": 400,
                "msg": "订单状态不允许"
            })

        order_info.status = 3
        order_info.save()

        return Response({
            "code": 200,
            "msg": "确认收货成功"
        })


# 演示 本地时间
class TestView(APIView):
    def get(self, request):
        order_list = OrderModel.objects.all()
        return render(request, "index.html", locals())
